/*
 * @Date: 2022-01-11 13:53:55
 * @Description: storage 工具类
 */

import initialState from './initialState'
import initialStateConfig from './initialState.config'

const VERSION = '1.0.3'

type Key = keyof typeof initialState
type Value<K extends Key> = typeof initialState[K]

/** @name 默认过期时间-不过期 */
const OUT_TIME_DAY = -1

/** @function 处理过期时间 */
function handlerOutTime($outTime: number, key?: string) {
  let outTime = $outTime
  const stateConfig = initialStateConfig[key]
  if ($outTime == -1 && stateConfig && stateConfig.outTime) {
    // 获取配置的过期时间
    outTime = typeof stateConfig.outTime == 'function' ? stateConfig.outTime() : stateConfig.outTime
  }
  // 如果传递的是秒数
  if (`${outTime}`.length === 10) {
    return outTime * 1000
    // 代表毫秒数
  }
  if (`${outTime}`.length === 13) {
    return outTime
  }
  // (1000 * 60 * 60 * 24) outTime 表示 1天  0.5半天  一天的毫秒数
  return outTime === -1 ? -1 : 1000 * 60 * 60 * 24 * outTime + Date.now()
}

const storage = {
  /** 同步获取本地存储值 不需要 JSON.parse
   * @param key
   * @param isDefaultValue 是否需要返回initialState中对应的默认值-默认为true
   * @param version-版本号默认VERSION-import { VERSION } from '@/config'
   * @returns {data} data
   */
  getItemSync<K extends Key>(key: K, isDefaultValue = true, version = VERSION): Value<K> {
    const defaultValue = isDefaultValue ? initialState[key] : undefined
    /* if (typeof defaultValue === 'object') {
      defaultValue = JSON.parse(JSON.stringify(defaultValue))
    } */

    let storage = wx.getStorageSync(key)
    if (storage) {
      storage = typeof storage != 'object' ? {} : storage
      const isVer = version ? version === storage.version : true
      if (storage.outTime > Date.now() && isVer) {
        // 根据过期时间和版本号控制
        if (storage.data == null) {
          return defaultValue
        }
        return storage.data
      }
      if (storage.outTime == -1 && isVer) {
        // 没有过期时间和版本号控制
        if (storage.data == null) {
          return defaultValue
        }
        return storage.data
      }
      wx.removeStorageSync(key)
      return defaultValue
    }
    return defaultValue
  },

  /** 同步设置本地存储值 不需要 JSON.stringify
   * @param key
   * @param data 存储的数据
   * @param outTime 默认缓存时间${OUT_TIME_DAY}天/时间戳,如果值为 -1 代表不过期
   * @param version 版本号默认VERSION import { VERSION } from '@/config'
   * @store {outTime: 过期的时间戳, data: 存储的数据, VERSION: 版本号}
   * @returns { storage: any }
   */
  setItemSync<K extends Key, V extends Value<K>>(key: K, data: V, options?: { outTime?: number; version?: string }) {
    const { outTime = OUT_TIME_DAY, version = VERSION } = options || {}
    const $outTime = handlerOutTime(outTime, key)
    const objData = {
      data,
      outTime: $outTime,
      version,
    }
    wx.setStorageSync(key, objData)
    return objData
  },

  /** 同步删除一项 */
  removeSync<K extends Key>(key: K): void {
    wx.removeStorageSync(key)
  },

  /** 同步删除所有数据 */
  clearSync(): void {
    wx.clearStorageSync()
  },

  /** 异步获取本地存储值 不需要 JSON.parse
   * @param key
   * @param isDefaultValue 是否需要返回initialState中对应的默认值-默认返回默认值
   * @param version-版本号默认VERSION-import { VERSION } from '@/config'
   * @returns {data} data
   */
  getItem<K extends Key>(key: K, isDefaultValue = true, version = VERSION): Promise<Value<K>> {
    const defaultValue = isDefaultValue ? initialState[key] : undefined
    /* if (typeof defaultValue === 'object') {
      defaultValue = JSON.parse(JSON.stringify(defaultValue))
    } */
    return new Promise((resolve) => {
      wx.getStorage({
        key,
        success(res) {
          let storage = res.data
          if (storage) {
            storage = typeof storage != 'object' ? {} : storage
            const isVer = version ? version === storage.version : true
            if (storage.outTime > Date.now() && isVer) {
              // 根据过期时间和版本号控制
              if (storage.data == null) {
                resolve(defaultValue)
              } else {
                resolve(storage.data)
              }
            } else if (storage.outTime == -1 && isVer) {
              // 没有过期时间和版本号控制
              if (storage.data == null) {
                resolve(defaultValue)
              } else {
                resolve(storage.data)
              }
            } else {
              // 已过期或者版本号不匹配
              resolve(defaultValue)
              wx.removeStorage({ key })
            }
          } else {
            resolve(defaultValue)
          }
        },
        fail() {
          resolve(defaultValue)
        },
      })
    })
  },

  /** 异步设置本地存储值 不需要 JSON.stringify
   * @param key
   * @param data 存储的数据
   * @param outTime 默认缓存时间${OUT_TIME_DAY}天/时间戳,如果值为 -1 代表不过期
   * @param version 版本号默认VERSION import { VERSION } from '@/config'
   * @store {outTime: 过期的时间戳, data: 存储的数据, VERSION: 版本号}
   * @returns Promise<{outTime: number, version: string, data: any}>
   */
  setItem<K extends Key, V extends Value<K>>(
    key: K,
    data: V,
    options?: { outTime?: number; version?: string },
  ): Promise<{ outTime: number; version: string; data: any }> {
    return new Promise((resolve) => {
      const { outTime = OUT_TIME_DAY, version = VERSION } = options || {}
      const $outTime = handlerOutTime(outTime, key)
      const objData = {
        data,
        outTime: $outTime,
        version,
      }
      wx.setStorage({
        key,
        data: objData,
        success() {
          resolve(objData)
        },
      })
    })
  },

  /** 异步设置本地存储对象中的data值 */
  setItemStorage<K extends Key, V extends Value<K>>(key: K, data: V): Promise<{ outTime: number; version: string; data: any }> {
    return new Promise((resolve) => {
      wx.getStorage({
        key,
        success(res) {
          const storage = res.data
          if (storage && storage.data) {
            storage.data = data
            wx.setStorageSync(key, storage)
            resolve(storage)
          }
        },
      })
    })
  },

  /** 异步删除一项数据 */
  remove<K extends Key>(key: K): Promise<any> {
    return new Promise((resolve, reject) => {
      wx.removeStorage({
        key,
        success(res) {
          resolve(res)
        },
        fail(err) {
          reject(err)
        },
      })
    })
  },

  /** 异步删除所有数据 */
  clear(): Promise<any> {
    return new Promise((resolve, reject) => {
      wx.clearStorage({
        success(res) {
          resolve(res)
        },
        fail(err) {
          reject(err)
        },
      })
    })
  },
}
  
declare global {
  type IStorage = typeof storage
}

export default storage
